/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.nanosl.norg.general.gui;

import com.nanosl.lib.date.JXDatePicker;
import com.nanosl.norg.ent.Address;
import com.nanosl.norg.ent.AddressPK;
import com.nanosl.norg.ent.AddressType;
import com.nanosl.norg.ent.City;
import com.nanosl.norg.ent.Person;
import com.nanosl.norg.ent.PersonHasAddress;
import com.nanosl.norg.ent.PersonHasAddressPK;
import com.nanosl.norg.ent.Phone;
import com.nanosl.norg.ent.PhoneType;
import com.nanosl.norg.util.NTopComponent;
import java.awt.Color;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.table.DefaultTableModel;
import org.netbeans.api.settings.ConvertAsProperties;
import org.netbeans.spi.actions.AbstractSavable;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;

/**
 * Top component which displays something.
 */
@ConvertAsProperties(
        dtd = "-//com.nanosl.credit.editor//PersonEditor//EN",
        autostore = false)
@TopComponent.Description(
        preferredID = "PersonEditorTopComponent",
        //iconBase="SET/PATH/TO/ICON/HERE", 
        persistenceType = TopComponent.PERSISTENCE_ALWAYS)
@TopComponent.Registration(mode = "editor", openAtStartup = false)
@ActionID(category = "Window", id = "com.nanosl.credit.editor.PersonEditorTopComponent")
@ActionReference(path = "Menu/Window" /*, position = 333 */)
@TopComponent.OpenActionRegistration(
        displayName = "#CTL_PersonEditorAction",
        preferredID = "PersonEditorTopComponent")
@Messages({
    "CTL_PersonEditorAction=PersonEditor",
    "CTL_PersonEditorTopComponent=PersonEditor Window",
    "HINT_PersonEditorTopComponent=This is a PersonEditor window"
})
public final class PersonEditorTopComponent extends NTopComponent {

    DefaultTableModel phoneTableModel, addressTableModel;

    public static void display() {
        PersonEditorTopComponent tc = (PersonEditorTopComponent) WindowManager.getDefault().findTopComponent("PersonEditorTopComponent");
        tc.open();
        tc.requestActive();
        tc.requestFocus();
    }

    public PersonEditorTopComponent() {
        initComponents();
        setName(Bundle.CTL_PersonEditorTopComponent());
        setToolTipText(Bundle.HINT_PersonEditorTopComponent());
        phoneTableModel = (DefaultTableModel) phoneTable.getModel();
        addressTableModel = (DefaultTableModel) addressTable.getModel();

    }

    private void fill(Person person) {
        nicTextField.setText(person.getNic());
        firstNameTextField.setText(person.getFirstName());
        lastNameTextField.setText(person.getLastName());
        datePicker.setDate(person.getDateOfBirth());
        fillAddressTable(person.getPersonHasAddressCollection());
        fillPhoneTable(person.getPhoneCollection());
    }

    private void fillAddressTable(Collection<PersonHasAddress> personHasAddresses) {
        addressTableModel.setRowCount(0);
        for (Iterator<PersonHasAddress> it = personHasAddresses.iterator(); it.hasNext();) {
            PersonHasAddress personHasAddress = it.next();
            PersonHasAddressPK personHasAddressPK = personHasAddress.getPersonHasAddressPK();
            Object[] row = {
                personHasAddressPK.getAddressAddressNumber(),
                personHasAddressPK.getAddressStreet(),
                manager.find(City.class, personHasAddressPK.getAddressCityCity()),
                personHasAddress.getAddressType()
            };
            addressTableModel.addRow(row);
        }
    }

    private void fillPhoneTable(Collection<Phone> phoneCollection) {
        phoneTableModel.setRowCount(0);
        for (Iterator<Phone> it = phoneCollection.iterator(); it.hasNext();) {
            Phone phone = it.next();
            Object[] row = {
                phone.getPhoneNumber(),
                phone.getPhoneType()
            };
            phoneTableModel.addRow(row);
        }
    }

    public void resetFields() {
        nicTextField.requestFocus();
        nicTextField.setText("");
        firstNameTextField.setText("");
        lastNameTextField.setText("");
        contactNumberTextField.setText("");
        addressNumberTextField.setText("");
        streetTextField.setText("");
        datePicker.setDate(null);
        fillPhoneTypeComboBox();
        fillCityComboBox();
        fillAddressTypeComboBox();
        phoneTableModel.setRowCount(0);
        addressTableModel.setRowCount(0);
    }

    private void fillPhoneTypeComboBox() {
        List<PhoneType> phoneTypes = manager.find(PhoneType.class);
        if (phoneTypes.isEmpty()) {
            PhoneTypeEditorTopComponent.display();
        }
        phoneTypeComboBox.setModel(new DefaultComboBoxModel<PhoneType>(phoneTypes.toArray(new PhoneType[phoneTypes.size()])));
    }

    private void fillCityComboBox() {
        List<City> citys = manager.find(City.class);
        if (citys.isEmpty()) {
            CityEditorTopComponent.display();
        }
        cityComboBox.setModel(new DefaultComboBoxModel<City>(citys.toArray(new City[citys.size()])));
    }

    private void fillAddressTypeComboBox() {
        List<AddressType> addressTypes = manager.find(AddressType.class);
        if (addressTypes.isEmpty()) {
            CityEditorTopComponent.display();
        }
        addressTypeComboBox.setModel(new DefaultComboBoxModel<Object>(addressTypes.toArray(new AddressType[addressTypes.size()])));
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jSpinner1 = new javax.swing.JSpinner();
        jScrollPane3 = new javax.swing.JScrollPane();
        jTextPane1 = new javax.swing.JTextPane();
        jPanel1 = new javax.swing.JPanel();
        nicTextField = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        firstNameTextField = new javax.swing.JTextField();
        jLabel4 = new javax.swing.JLabel();
        lastNameTextField = new javax.swing.JTextField();
        jLabel8 = new javax.swing.JLabel();
        contactNumberTextField = new javax.swing.JTextField();
        phoneTypeComboBox = new javax.swing.JComboBox();
        jScrollPane1 = new javax.swing.JScrollPane();
        phoneTable = new javax.swing.JTable();
        jLabel10 = new javax.swing.JLabel();
        addressNumberTextField = new javax.swing.JTextField();
        jLabel11 = new javax.swing.JLabel();
        streetTextField = new javax.swing.JTextField();
        addressTypeComboBox = new javax.swing.JComboBox();
        jLabel13 = new javax.swing.JLabel();
        cityComboBox = new javax.swing.JComboBox();
        jLabel12 = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        addressTable = new javax.swing.JTable();
        saveButton = new javax.swing.JButton();
        clearButton = new javax.swing.JButton();
        jLabel9 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        datePicker = new JXDatePicker();

        jScrollPane3.setViewportView(jTextPane1);

        jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));

        nicTextField.setText(org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.nicTextField.text_1")); // NOI18N
        nicTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nicTextFieldActionPerformed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.jLabel1.text_1")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.jLabel3.text_1")); // NOI18N

        firstNameTextField.setText(org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.firstNameTextField.text_1")); // NOI18N
        firstNameTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                firstNameTextFieldActionPerformed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.jLabel4.text_1")); // NOI18N

        lastNameTextField.setText(org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.lastNameTextField.text_1")); // NOI18N
        lastNameTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                lastNameTextFieldActionPerformed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(jLabel8, org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.jLabel8.text_1")); // NOI18N

        contactNumberTextField.setText(org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.contactNumberTextField.text_1")); // NOI18N
        contactNumberTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                contactNumberTextFieldActionPerformed(evt);
            }
        });

        phoneTypeComboBox.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                phoneTypeComboBoxKeyPressed(evt);
            }
        });

        phoneTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Number", "Type"
            }
        ) {
            boolean[] canEdit = new boolean [] {
                false, false
            };

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        phoneTable.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                phoneTableKeyPressed(evt);
            }
        });
        jScrollPane1.setViewportView(phoneTable);

        org.openide.awt.Mnemonics.setLocalizedText(jLabel10, org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.jLabel10.text_1")); // NOI18N

        addressNumberTextField.setText(org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.addressNumberTextField.text_1")); // NOI18N
        addressNumberTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addressNumberTextFieldActionPerformed(evt);
            }
        });
        addressNumberTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                addressNumberTextFieldKeyReleased(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(jLabel11, org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.jLabel11.text_1")); // NOI18N

        streetTextField.setText(org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.streetTextField.text_1")); // NOI18N
        streetTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                streetTextFieldActionPerformed(evt);
            }
        });

        addressTypeComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addressTypeComboBoxActionPerformed(evt);
            }
        });
        addressTypeComboBox.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                addressTypeComboBoxKeyPressed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(jLabel13, org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.jLabel13.text_1")); // NOI18N

        cityComboBox.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                cityComboBoxKeyPressed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(jLabel12, org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.jLabel12.text_1")); // NOI18N

        addressTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Number", "Street", "City", "Type"
            }
        ) {
            boolean[] canEdit = new boolean [] {
                false, false, true, false
            };

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        addressTable.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                addressTableKeyPressed(evt);
            }
        });
        jScrollPane2.setViewportView(addressTable);

        org.openide.awt.Mnemonics.setLocalizedText(saveButton, org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.saveButton.text_1")); // NOI18N
        saveButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveButtonActionPerformed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(clearButton, org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.clearButton.text_1")); // NOI18N
        clearButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                clearButtonActionPerformed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(jLabel9, org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.jLabel9.text_1")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(PersonEditorTopComponent.class, "PersonEditorTopComponent.jLabel2.text_1")); // NOI18N

        datePicker.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                datePickerActionPerformed(evt);
            }
        });
        datePicker.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                datePickerKeyPressed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGap(10, 10, 10)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
                                    .addComponent(jLabel10)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(addressNumberTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 74, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(jLabel11)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(streetTextField))
                                .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
                                    .addComponent(jLabel12)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(cityComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 169, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(jLabel13)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(addressTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE)))
                            .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 404, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(jPanel1Layout.createSequentialGroup()
                                .addComponent(saveButton)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(clearButton))))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel8)
                            .addComponent(jLabel9)
                            .addComponent(jLabel2)
                            .addComponent(jLabel1)
                            .addComponent(jLabel3)
                            .addComponent(jLabel4))
                        .addGap(18, 18, 18)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(contactNumberTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(phoneTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(firstNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(nicTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(lastNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(datePicker, javax.swing.GroupLayout.PREFERRED_SIZE, 151, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 176, javax.swing.GroupLayout.PREFERRED_SIZE))))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {contactNumberTextField, datePicker, firstNameTextField, lastNameTextField, nicTextField, phoneTypeComboBox});

        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(nicTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(firstNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel4)
                    .addComponent(lastNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(datePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel8)
                    .addComponent(contactNumberTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(phoneTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel9))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 106, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(25, 25, 25)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel10)
                    .addComponent(addressNumberTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel11)
                    .addComponent(streetTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel12)
                    .addComponent(cityComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel13)
                    .addComponent(addressTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 99, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(saveButton)
                    .addComponent(clearButton))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void nicTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nicTextFieldActionPerformed
        String nic = nicTextField.getText().trim();
        if (!isNIC(nic)) {
            errorField(nicTextField);
            return;
        }
        nicTextField.setBackground(Color.WHITE);
        Person person = manager.find(Person.class, nic);
        if (person != null) {
            fill(person);
        }
        firstNameTextField.requestFocus();
    }//GEN-LAST:event_nicTextFieldActionPerformed

    private void firstNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_firstNameTextFieldActionPerformed
        if (isText(firstNameTextField.getText().trim())) {
            firstNameTextField.setBackground(Color.WHITE);
            lastNameTextField.requestFocus();
        } else {
            errorField(firstNameTextField);
        }
    }//GEN-LAST:event_firstNameTextFieldActionPerformed

    private void lastNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_lastNameTextFieldActionPerformed
        if (isText(lastNameTextField.getText().trim())) {
            lastNameTextField.setBackground(Color.WHITE);
            datePicker.requestFocus();
        } else {
            errorField(lastNameTextField);
        }
    }//GEN-LAST:event_lastNameTextFieldActionPerformed

    private void contactNumberTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_contactNumberTextFieldActionPerformed
        String phoneNumber = contactNumberTextField.getText().trim();
        if (isPhone(phoneNumber)) {
            phoneTypeComboBox.requestFocus();
        } else if (phoneNumber.equals("")) {
            addressNumberTextField.requestFocus();
        }
    }//GEN-LAST:event_contactNumberTextFieldActionPerformed

    private void phoneTypeComboBoxKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_phoneTypeComboBoxKeyPressed
        String number = contactNumberTextField.getText().trim();
        if (evt.getKeyCode() == 10 && isPhone(number)) {
            Object[] rowData = {number, phoneTypeComboBox.getSelectedItem()};
            phoneTableModel.addRow(rowData);
            contactNumberTextField.setText("");
            contactNumberTextField.requestFocus();
        } else if (evt.getKeyCode() == 192) {
            addressNumberTextField.requestFocus();
        }
    }//GEN-LAST:event_phoneTypeComboBoxKeyPressed

    private void phoneTableKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_phoneTableKeyPressed
        if (evt.getKeyCode() == 127 && phoneTable.getSelectedRow() > -1) {
            phoneTableModel.removeRow(phoneTable.getSelectedRow());
        }
    }//GEN-LAST:event_phoneTableKeyPressed

    private void addressNumberTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addressNumberTextFieldActionPerformed
        streetTextField.requestFocus();
    }//GEN-LAST:event_addressNumberTextFieldActionPerformed

    private void addressNumberTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_addressNumberTextFieldKeyReleased

    }//GEN-LAST:event_addressNumberTextFieldKeyReleased

    private void streetTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_streetTextFieldActionPerformed
        cityComboBox.requestFocus();
    }//GEN-LAST:event_streetTextFieldActionPerformed

    private void addressTypeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addressTypeComboBoxActionPerformed
        if (!addressNumberTextField.getText().trim().equals("")) {
            addressNumberTextField.requestFocus();
        }
    }//GEN-LAST:event_addressTypeComboBoxActionPerformed

    private void addressTypeComboBoxKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_addressTypeComboBoxKeyPressed
        if (evt.getKeyCode() == 10) {
            Object[] rowData = {addressNumberTextField.getText().trim(), streetTextField.getText().trim(), cityComboBox.getSelectedItem(), addressTypeComboBox.getSelectedItem()};
            addressTableModel.addRow(rowData);
            addressNumberTextField.setText("");
            streetTextField.setText("");
            addressNumberTextField.requestFocus();
        } else if (evt.getKeyCode() == 192) {
            saveButton.requestFocus();
        }
    }//GEN-LAST:event_addressTypeComboBoxKeyPressed

    private void cityComboBoxKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_cityComboBoxKeyPressed
        if (evt.getKeyCode() == 10) {
            addressTypeComboBox.requestFocus();
        }
    }//GEN-LAST:event_cityComboBoxKeyPressed

    private void addressTableKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_addressTableKeyPressed
        if (evt.getKeyCode() == 127 && addressTable.getSelectedRow() > -1) {
            addressTableModel.removeRow(addressTable.getSelectedRow());
        }
    }//GEN-LAST:event_addressTableKeyPressed

    private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed
        try {
            new PersonSavable().handleSave();
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
    }//GEN-LAST:event_saveButtonActionPerformed

    private void clearButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clearButtonActionPerformed
        resetFields();
    }//GEN-LAST:event_clearButtonActionPerformed

    private void datePickerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_datePickerActionPerformed
        if (datePicker.getDate() == null) {
        } else {
            contactNumberTextField.requestFocus();
        }
    }//GEN-LAST:event_datePickerActionPerformed

    private void datePickerKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_datePickerKeyPressed
        //        if (evt.getKeyCode() == 10) {
            //            amountTextField.requestFocus();
            //        }
    }//GEN-LAST:event_datePickerKeyPressed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTextField addressNumberTextField;
    private javax.swing.JTable addressTable;
    private javax.swing.JComboBox addressTypeComboBox;
    private javax.swing.JComboBox cityComboBox;
    private javax.swing.JButton clearButton;
    private javax.swing.JTextField contactNumberTextField;
    private org.jdesktop.swingx.JXDatePicker datePicker;
    private javax.swing.JTextField firstNameTextField;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel13;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JSpinner jSpinner1;
    private javax.swing.JTextPane jTextPane1;
    private javax.swing.JTextField lastNameTextField;
    private javax.swing.JTextField nicTextField;
    private javax.swing.JTable phoneTable;
    private javax.swing.JComboBox phoneTypeComboBox;
    private javax.swing.JButton saveButton;
    private javax.swing.JTextField streetTextField;
    // End of variables declaration//GEN-END:variables

    @Override
    public void componentOpened() {
        resetFields();
    }

    @Override
    public void componentClosed() {
        // TODO add custom code on component closing
    }

    void writeProperties(java.util.Properties p) {
        // better to version settings since initial version as advocated at
        // http://wiki.apidesign.org/wiki/PropertyFiles
        p.setProperty("version", "1.0");
        // TODO store your settings
    }

    void readProperties(java.util.Properties p) {
        String version = p.getProperty("version");
        // TODO read your settings according to their version
    }

    private class PersonSavable extends AbstractSavable {

        String nic, firstName, lastName;

        PersonSavable() {
            register();
        }

        @Override
        protected String findDisplayName() {
            firstName = firstNameTextField.getText();
            lastName = lastNameTextField.getText();
            return firstName + " " + lastName;
        }

        @Override
        protected void handleSave() throws IOException {
            if (isVallid()) {
                NotifyDescriptor.Confirmation message = new NotifyDescriptor.Confirmation(
                        "Do you want to save \n " + firstName + " " + nic + "?", NotifyDescriptor.OK_CANCEL_OPTION, NotifyDescriptor.QUESTION_MESSAGE);
                Object result = DialogDisplayer.getDefault().notify(message);
                if (NotifyDescriptor.YES_OPTION.equals(result)) {

                    Person person = manager.find(Person.class, nic);
                    if (person == null) {
                        person = new Person(nic);
                    }
                    person.setFirstName(firstName);
                    person.setLastName(lastName);
                    Date dateOfBirth = datePicker.getDate();
                    if (dateOfBirth != null) {
                        person.setDateOfBirth(dateOfBirth);
                    }
                    Collection<Phone> phones = person.getPhoneCollection();
                    phones = phones == null ? new ArrayList<Phone>() : phones;
                    phones.clear(); // Added by request 2013-10-17
                    int rowCount = phoneTable.getRowCount();
                    for (int i = 0; i < rowCount; i++) {
                        String phoneNumber = phoneTable.getValueAt(i, 0).toString();
                        PhoneType phoneType = (PhoneType) phoneTable.getValueAt(i, 1);
                        Phone phone = new Phone(phoneNumber);
                        phone.setPhoneType(phoneType);
                        if (!phones.contains(phone)) {
                            phones.add(phone);
                            manager.update(phone);
                        }
                    }
                    person.setPhoneCollection(phones);
                    Collection<PersonHasAddress> personHasAddresses = person.getPersonHasAddressCollection();
                    personHasAddresses = personHasAddresses == null ? new ArrayList<PersonHasAddress>() : personHasAddresses;
                    personHasAddresses.clear(); // Added by request 2013-10-17
                    rowCount = addressTable.getRowCount();
                    for (int i = 0; i < rowCount; i++) {
                        String addressNumber = addressTable.getValueAt(i, 0).toString();
                        String addressStreet = addressTable.getValueAt(i, 1).toString();
                        City city = (City) addressTable.getValueAt(i, 2);
                        AddressType addressType = (AddressType) addressTable.getValueAt(i, 3);
                        Address address = new Address(new AddressPK(addressNumber, addressStreet, city.getCity()));
                        PersonHasAddress personHasAddress = new PersonHasAddress(new PersonHasAddressPK(person.getNic(), addressNumber, addressStreet, city.getCity()));
                        personHasAddress.setAddress(address);
                        personHasAddress.setAddressType(addressType);
                        personHasAddress.setPerson(person);
                        manager.update(address);                        
                        manager.update(personHasAddress);
                        personHasAddresses.add(personHasAddress);
                    }
                    person.setPersonHasAddressCollection(personHasAddresses);
                    manager.update(person);
                    resetFields();
                    unregister();
                }
            } else {
                showError("Incomplete Information");
            }
        }

        PersonEditorTopComponent tc() {
            return PersonEditorTopComponent.this;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof PersonSavable) {
                PersonSavable m = (PersonSavable) obj;
                return tc() == m.tc();
            }
            return false;
        }

        @Override
        public int hashCode() {
            return tc().hashCode();
        }

        private boolean isVallid() {
            nic = nicTextField.getText();
            if (!isNIC(nic)) {
                return false;
            }
            firstName = firstNameTextField.getText().trim();
            if (firstName.length() == 0) {
                return false;
            }
            lastName = lastNameTextField.getText().trim();
            if (lastName.length() == 0) {
                return false;
            }
            return true;
        }
    }
}
